﻿using System;
using System.Collections.Generic;
using System.IO;
using Terraria.Map;
using Terraria.Social;
using Terraria.Utilities;

namespace Terraria.ModLoader.IO
{
	// Token: 0x020002CA RID: 714
	internal static class MapIO
	{
		// Token: 0x06001BD2 RID: 7122 RVA: 0x004323B4 File Offset: 0x004305B4
		internal static void WriteModFile(string path, bool isCloudSave)
		{
			path = Path.ChangeExtension(path, ".tmap");
			bool flag;
			byte[] data;
			using (MemoryStream memoryStream = new MemoryStream())
			{
				using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
				{
					flag = MapIO.WriteModMap(binaryWriter);
					binaryWriter.Flush();
					data = memoryStream.ToArray();
				}
			}
			if (flag)
			{
				FileUtilities.WriteAllBytes(path, data, isCloudSave);
				return;
			}
			if (isCloudSave && SocialAPI.Cloud != null)
			{
				SocialAPI.Cloud.Delete(path);
				return;
			}
			File.Delete(path);
		}

		// Token: 0x06001BD3 RID: 7123 RVA: 0x0043244C File Offset: 0x0043064C
		internal static void ReadModFile(string path, bool isCloudSave)
		{
			path = Path.ChangeExtension(path, ".tmap");
			if (!FileUtilities.Exists(path, isCloudSave))
			{
				return;
			}
			byte[] buffer = FileUtilities.ReadAllBytes(path, isCloudSave);
			using (MemoryStream memoryStream = new MemoryStream(buffer))
			{
				using (BinaryReader binaryReader = new BinaryReader(memoryStream))
				{
					MapIO.ReadModMap(binaryReader);
				}
			}
		}

		// Token: 0x06001BD4 RID: 7124 RVA: 0x004324C0 File Offset: 0x004306C0
		internal static bool WriteModMap(BinaryWriter writer)
		{
			ISet<ushort> set = new HashSet<ushort>();
			for (int i = 0; i < Main.maxTilesX; i++)
			{
				for (int j = 0; j < Main.maxTilesY; j++)
				{
					ushort type = Main.Map[i, j].Type;
					if (type >= MapHelper.modPosition)
					{
						set.Add(type);
					}
				}
			}
			if (set.Count == 0)
			{
				return false;
			}
			writer.Write((ushort)set.Count);
			foreach (ushort num in set)
			{
				writer.Write(num);
				if (MapLoader.entryToTile.ContainsKey(num))
				{
					ModTile tile = TileLoader.GetTile((int)MapLoader.entryToTile[num]);
					writer.Write(true);
					writer.Write(tile.mod.Name);
					writer.Write(tile.Name);
					writer.Write(num - MapHelper.tileLookup[(int)tile.Type]);
				}
				else if (MapLoader.entryToWall.ContainsKey(num))
				{
					ModWall wall = WallLoader.GetWall((int)MapLoader.entryToWall[num]);
					writer.Write(false);
					writer.Write(wall.mod.Name);
					writer.Write(wall.Name);
					writer.Write(num - MapHelper.wallLookup[(int)wall.Type]);
				}
				else
				{
					writer.Write(true);
					writer.Write("");
					writer.Write("");
					writer.Write(0);
				}
			}
			MapIO.WriteMapData(writer);
			return true;
		}

		// Token: 0x06001BD5 RID: 7125 RVA: 0x00432670 File Offset: 0x00430870
		internal static void ReadModMap(BinaryReader reader)
		{
			IDictionary<ushort, ushort> dictionary = new Dictionary<ushort, ushort>();
			ushort num = reader.ReadUInt16();
			for (ushort num2 = 0; num2 < num; num2 += 1)
			{
				ushort key = reader.ReadUInt16();
				bool flag = reader.ReadBoolean();
				string name = reader.ReadString();
				string name2 = reader.ReadString();
				ushort num3 = reader.ReadUInt16();
				Mod mod = ModLoader.GetMod(name);
				ushort value = 0;
				if (mod != null)
				{
					if (flag)
					{
						ushort num4 = (ushort)mod.TileType(name2);
						if (num4 != 0)
						{
							if ((int)num3 >= MapLoader.modTileOptions(num4))
							{
								num3 = 0;
							}
							value = (ushort)MapHelper.TileToLookup((int)num4, (int)num3);
						}
					}
					else
					{
						ushort num5 = (ushort)mod.WallType(name2);
						if (num5 != 0)
						{
							if ((int)num3 >= MapLoader.modWallOptions(num5))
							{
								num3 = 0;
							}
							value = MapHelper.wallLookup[(int)num5] + num3;
						}
					}
				}
				dictionary[key] = value;
			}
			MapIO.ReadMapData(reader, dictionary);
		}

		// Token: 0x06001BD6 RID: 7126 RVA: 0x00432740 File Offset: 0x00430940
		internal static void WriteMapData(BinaryWriter writer)
		{
			byte b = 0;
			bool flag = false;
			int x = 0;
			int y = 0;
			do
			{
				MapTile mapTile = Main.Map[x, y];
				if (mapTile.Type >= MapHelper.modPosition && mapTile.Light > 18)
				{
					if (!flag)
					{
						writer.Write(b);
						b = 0;
					}
					else
					{
						flag = false;
					}
					MapIO.WriteMapTile(ref x, ref y, writer, ref flag);
				}
				else
				{
					b += 1;
					if (b == 255)
					{
						writer.Write(b);
						b = 0;
					}
				}
			}
			while (MapIO.NextTile(ref x, ref y));
			if (b > 0)
			{
				writer.Write(b);
			}
		}

		// Token: 0x06001BD7 RID: 7127 RVA: 0x004327C8 File Offset: 0x004309C8
		internal static void ReadMapData(BinaryReader reader, IDictionary<ushort, ushort> table)
		{
			int num = 0;
			int num2 = 0;
			bool flag = false;
			for (;;)
			{
				if (!flag)
				{
					byte b;
					for (b = reader.ReadByte(); b == 255; b = reader.ReadByte())
					{
						for (byte b2 = 0; b2 < 255; b2 += 1)
						{
							if (!MapIO.NextTile(ref num, ref num2))
							{
								return;
							}
						}
					}
					for (byte b3 = 0; b3 < b; b3 += 1)
					{
						if (!MapIO.NextTile(ref num, ref num2))
						{
							return;
						}
					}
				}
				else
				{
					flag = false;
				}
				MapIO.ReadMapTile(ref num, ref num2, table, reader, ref flag);
				if (!MapIO.NextTile(ref num, ref num2))
				{
					return;
				}
			}
		}

		// Token: 0x06001BD8 RID: 7128 RVA: 0x00432850 File Offset: 0x00430A50
		internal static void WriteMapTile(ref int i, ref int j, BinaryWriter writer, ref bool nextModTile)
		{
			MapTile mapTile = Main.Map[i, j];
			byte b = 0;
			byte[] array = new byte[9];
			int num = 1;
			array[num] = (byte)mapTile.Type;
			num++;
			array[num] = (byte)(mapTile.Type >> 8);
			num++;
			if (mapTile.Light < 255)
			{
				b |= 1;
				array[num] = mapTile.Light;
				num++;
			}
			if (mapTile.Color > 0)
			{
				b |= 2;
				array[num] = mapTile.Color;
				num++;
			}
			int num2 = i;
			int num3 = j;
			uint num4 = 0u;
			while (MapIO.NextTile(ref num2, ref num3))
			{
				MapTile mapTile2 = Main.Map[num2, num3];
				if (mapTile.Equals(ref mapTile2) && num4 < 4294967295u)
				{
					num4 += 1u;
					i = num2;
					j = num3;
				}
				else
				{
					if (mapTile2.Type >= MapHelper.modPosition && mapTile2.Light > 18)
					{
						b |= 32;
						nextModTile = true;
						break;
					}
					break;
				}
			}
			if (num4 > 0u)
			{
				b |= 4;
				array[num] = (byte)num4;
				num++;
				if (num4 > 255u)
				{
					b |= 8;
					array[num] = (byte)(num4 >> 8);
					num++;
					if (num4 > 65535u)
					{
						b |= 16;
						array[num] = (byte)(num4 >> 16);
						num++;
						array[num] = (byte)(num4 >> 24);
						num++;
					}
				}
			}
			array[0] = b;
			writer.Write(array, 0, num);
		}

		// Token: 0x06001BD9 RID: 7129 RVA: 0x004329A4 File Offset: 0x00430BA4
		internal static void ReadMapTile(ref int i, ref int j, IDictionary<ushort, ushort> table, BinaryReader reader, ref bool nextModTile)
		{
			byte b = reader.ReadByte();
			ushort type = table[reader.ReadUInt16()];
			byte light = ((b & 1) == 1) ? reader.ReadByte() : byte.MaxValue;
			byte color = ((b & 2) == 2) ? reader.ReadByte() : 0;
			MapTile mapTile = MapTile.Create(type, light, color);
			Main.Map.SetTile(i, j, ref mapTile);
			if ((b & 4) == 4)
			{
				uint num;
				if ((b & 16) == 16)
				{
					num = reader.ReadUInt32();
				}
				else if ((b & 8) == 8)
				{
					num = (uint)reader.ReadUInt16();
				}
				else
				{
					num = (uint)reader.ReadByte();
				}
				for (uint num2 = 0u; num2 < num; num2 += 1u)
				{
					MapIO.NextTile(ref i, ref j);
					mapTile = MapTile.Create(type, light, color);
					Main.Map.SetTile(i, j, ref mapTile);
				}
			}
			if ((b & 32) == 32)
			{
				nextModTile = true;
			}
		}

		// Token: 0x06001BDA RID: 7130 RVA: 0x00013F87 File Offset: 0x00012187
		private static bool NextTile(ref int i, ref int j)
		{
			j++;
			if (j >= Main.maxTilesY)
			{
				j = 0;
				i++;
				if (i >= Main.maxTilesX)
				{
					return false;
				}
			}
			return true;
		}
	}
}
